/*******************************************************************************
 * Copyright (c) 2010, 2010 Xbeam Project and ChenZhiKong.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License. 
 *******************************************************************************/
package org.bellusoft.xbeam.framework;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Dictionary;
import java.util.Enumeration;
import java.util.List;
import java.util.Map;
import java.util.concurrent.locks.ReentrantLock;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleException;
import org.osgi.framework.ServiceReference;
import org.osgi.framework.Version;

/**
 *
 *
 */
public class HostBundle implements Bundle{
	
	//TODO: Security, Service Layer related methods And adapt method
	
	private BundleStorage storage ; 
	
	private BundleContext context ; 
	
	private final List<Module> obsoleteModules = new ArrayList<Module>(0);
	
	private Module currentModule ;
	
	private ReentrantLock lock = new ReentrantLock() ; 
	
	public int compareTo(Bundle o) {
		return (int)(storage.getBundleId()-o.getBundleId());
	}

	public int getState() {
		lock.lock();
		try{
			return currentModule.getState();
		}finally{
			lock.unlock() ; 
		}
	}
	
	public void start(int options) throws BundleException {
		currentModule.start(options);
	}

	public void start() throws BundleException {
		currentModule.start();
	}

	public void stop(int options) throws BundleException {
		currentModule.stop();
	}

	public void stop() throws BundleException {
		currentModule.stop() ; 
	}

	public void update(InputStream input) throws BundleException {
		
		lock.lock() ; 
		try{
			
			if(currentModule.getState()==UNINSTALLED){
				throw new IllegalStateException("Uninstalled bundle can not be updated");
			}
			
			Transaction t = storage.newTranscation() ; 
			Module newModule = null ; 
			try{
				t.begin();
				newModule = t.update(input);
				t.commit();
			}catch (Throwable th) {
				try{
					t.rollback();
				}catch (Exception e) {
					// TODO: handle exception
				}
				throw new BundleException("Error when updating bundle", th);
			}
			
			if((getState()&(ACTIVE|STARTING|STOPPING))!=0){
				stop() ; 
			}
			
			if(!currentModule.isExportPackageUsed()){
				currentModule.unresolve() ; 
			}else{
				obsoleteModules.add(currentModule);
			}
			currentModule = newModule ; 
			
		}finally{
			lock.unlock() ; 
		}
		
	}

	public void update() throws BundleException {
		update(null);
	}

	public void uninstall() throws BundleException {
		currentModule.uninstall() ; 
	}

	public Dictionary<String, String> getHeaders() {
		return currentModule.getHeaders() ; 
	}

	public long getBundleId() {
		return storage.getBundleId();
	}

	public String getLocation() {
		return storage.getLocation();
	}

	public ServiceReference<?>[] getRegisteredServices() {
		throw new UnsupportedOperationException("TODO");
	}

	public ServiceReference<?>[] getServicesInUse() {
		throw new UnsupportedOperationException("TODO");
	}

	public boolean hasPermission(Object permission) {
		throw new UnsupportedOperationException("TODO");
	}

	public URL getResource(String name) {
		return currentModule.getResource(name);
	}

	public Dictionary<String, String> getHeaders(String locale) {
		return currentModule.getHeaders(locale);
	}

	public String getSymbolicName() {
		return currentModule.getSymbolicName();
	}

	public Class<?> loadClass(String name) throws ClassNotFoundException {
		return currentModule.loadClass(name);
	}

	public Enumeration<URL> getResources(String name) throws IOException {
		return currentModule.getResources(name);
	}

	public Enumeration<String> getEntryPaths(String path) {
		return currentModule.getEntryPaths(path);
	}

	public URL getEntry(String path) {
		return currentModule.getEntry(path);
	}

	public long getLastModified() {
		return storage.getLastModifyTime();
	}

	public Enumeration<URL> findEntries(String path, String filePattern,
			boolean recurse) {
		return currentModule.findEntries(path, filePattern, recurse);
	}

	public BundleContext getBundleContext() {
		return context;
	}

	public Map<X509Certificate, List<X509Certificate>> getSignerCertificates(
			int signersType) {
		throw new UnsupportedOperationException("TODO");
	}

	public Version getVersion() {
		return currentModule.getVersion();
	}

	public <A> A adapt(Class<A> type) {
		throw new UnsupportedOperationException("TODO");
	}

	public File getDataFile(String filename) {
		return storage.getDataFile(filename);
	}

	/**
	 * 
	 */
	public void startAccordingPersistStartSetting() {
		// TODO Auto-generated method stub
		
	}

}
